home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / audio / drive / Curve.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  4.6 KB  |  177 lines

  1. /*
  2.  * Copyright 1992-1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. //////////////////////////////////////////////////////////////////////
  18. // Curve.c++ - definition of the curve class
  19. //
  20. // This class defines a curved stretch of road. It is
  21. // derived from the stretch abstract base class.
  22. //////////////////////////////////////////////////////////////////////
  23.  
  24. #include <math.h>
  25. #include "Stretch.h"
  26. #include "Curve.h"
  27. #include "MiscMath.h"
  28.  
  29. Curve::Curve(
  30.     Stretch *prev, Stretch *next, 
  31.     float radius, float width, float turn_angle, float bank_angle)
  32.     : Stretch(prev, next)
  33. {
  34.     _type = CURVE;
  35.     _step = 30.0;
  36.     
  37.     // specified in degrees, stored as radians
  38.     // Right Hand Rules (!), so positive is curve to left
  39.     _turn_angle = turn_angle*M_PI/180.0;
  40.     _hill_angle = _hill_radius = 0.0;
  41.     _bank_angle = bank_angle*M_PI/180.0;
  42.  
  43.     _turn_radius = radius;
  44.     _width = width;
  45.     _length = fabs(_turn_radius*_turn_angle);
  46.  
  47.     Stretch::compute_step();
  48.     Stretch::allocate_data();
  49.     
  50.     // find the accumulated offset and orientation 
  51.     SbVec3f prev_offset;
  52.     SbRotation prev_orientation;
  53.     Stretch::find_previous(prev_offset, prev_orientation);
  54.     
  55.     make_curve(prev_offset,prev_orientation);
  56.     
  57.     // match up ends
  58.     Stretch::match_ends();
  59.  
  60.     Stretch::init_scenery();
  61. }
  62.  
  63.  
  64. Curve::~Curve()
  65. {
  66. }
  67.  
  68.  
  69. void Curve::make_curve(SbVec3f prev_offset, SbRotation prev_orientation)
  70. {
  71.     SbVec3f left, middle, right;
  72.  
  73.     // set initial values for x coordinates
  74.     left.setValue(- _width/2.0,0.0,0.0);
  75.     middle.setValue(0.0,0.0,0.0);
  76.     right.setValue(_width/2.0,0.0,0.0);
  77.  
  78.     float bank_step = _bank_angle/(_length/_step);
  79.     float bank = 0.0;
  80.  
  81.     float inside_radius = _turn_radius - _width/2.0;
  82.     float outside_radius = _turn_radius + _width/2.0;
  83.  
  84.     float z = 0.0;
  85.     
  86.     for (int i = 0; i < _num_markers; i++)
  87.     {
  88.         if (_turn_angle > 0.0)
  89.         {            
  90.             right[0] = outside_radius*fcos(_turn_angle * z/_length) - 
  91.                         _turn_radius;
  92.             left[0] = inside_radius*fcos(_turn_angle * z/_length) - 
  93.                         _turn_radius;
  94.         
  95.             right[2] = - outside_radius * fsin(_turn_angle * z/_length);
  96.             left[2] = - inside_radius * fsin(_turn_angle * z/_length);
  97.         }
  98.         else
  99.         {
  100.             left[0] = _turn_radius - 
  101.                 outside_radius*fcos(_turn_angle * z/_length);
  102.             right[0] = _turn_radius - 
  103.                 inside_radius*fcos(_turn_angle * z/_length);
  104.                 
  105.             left[2] = outside_radius * fsin(_turn_angle * z/_length);
  106.             right[2] = inside_radius * fsin(_turn_angle * z/_length);
  107.         }
  108.  
  109.         middle = (left + right)/2.0;            
  110.  
  111.         // Compute the normal
  112.         _data[i].normal.setValue(0.0,1.0,0.0);
  113.  
  114.         _data[i].left = left;
  115.         _data[i].middle = middle;
  116.         _data[i].right = right;
  117.  
  118.         // rotate the data and the normals about the center
  119.         // of the road by bank radians counter clockwise
  120.         rotate_bank(i,bank);
  121.         bank += bank_step;
  122.  
  123.         z += _step;
  124.     }
  125.  
  126.     Stretch::transform_data(prev_offset, prev_orientation);
  127.  
  128.     // find the "center" of the curve, the point which the road
  129.     // radius rotates about
  130.     SbVec3f side_vec;
  131.     if (_turn_angle > 0.0)
  132.         side_vec = this->get_side_direction(0,RIGHT);
  133.     else
  134.         side_vec = this->get_side_direction(0,LEFT);
  135.  
  136.     side_vec.normalize();
  137.     side_vec = side_vec * _turn_radius;
  138.     _center = _data[0].middle + side_vec;
  139.  
  140.     // find angle occupied between markers
  141.     _marker_angle = fabs(_turn_angle)/(float)(_num_markers - 1);
  142.  
  143.     // find orientation from origin to end of this stretch
  144.     SbVec3f up(0.0,1.0,0.0);
  145.     SbRotation this_quat(_data[0].normal,_data[_num_markers-1].normal);
  146.     SbRotation turn_quat(up, _turn_angle);
  147.  
  148.     _orientation = turn_quat * this_quat * prev_orientation;
  149. }
  150.  
  151.  
  152. // Returns offset, 0.0 - 1.0, indicating how far along position
  153. // is from given marker on this stretch
  154. Boolean Curve::get_marker_offset(
  155.     int marker,
  156.     const SbVec3f position, 
  157.     float &new_offset)
  158. {
  159.     SbVec3f marker_vec = _data[marker].middle - _center;
  160.     SbVec3f car_vec = position - _center;
  161.  
  162.     float angle = angle_between(marker_vec, car_vec);
  163.  
  164.     if (angle > _marker_angle)
  165.     {
  166.         new_offset =  ((angle - _marker_angle)/_marker_angle);
  167.         return TRUE;
  168.     }
  169.     else
  170.     {
  171.         new_offset = angle/_marker_angle;
  172.         return FALSE;
  173.     }
  174. }
  175.  
  176.  
  177.